
package com.umeox.phone.util;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Service;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.os.StatFs;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;

import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.ITelephony;
import com.umeox.moto.common.log.Logger;
import com.umeox.moto.common.utils.DateUtils;
import com.umeox.phone.BuildConfig;
import com.umeox.phone.ui.InCallUIActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Method;

public class Utils {
    private static final String TAG = Utils.class.getSimpleName();

    /**
     * 发送挂断电话的广播
     *
     * @param ctx 上下文对象
     */
    public static void sendEndCallBroadCast(Context ctx, int callType, long endCallTime) {
        Utils.closeSpeaker(ctx);
        Intent i = new Intent();
        i.setAction(InCallUIActivity.ACTION_END_CALL);
        i.putExtra("callType", callType);
        i.putExtra("endCallTime", endCallTime);
        ctx.sendBroadcast(i);
    }


    public static void sendListenCallEndBroadCast(Context ctx) {
        Intent i = new Intent();
        i.setAction(InCallUIActivity.ACTION_LISTEN_CALL_END);
        ctx.sendBroadcast(i);
    }

    public static void sendOutCallConnectBroadCast(Context ctx) {
        Intent i = new Intent();
        i.setAction(InCallUIActivity.ACTION_OUT_CALL_CONNECT);
        ctx.sendBroadcast(i);
    }

    public static void sendCallStateBroadCast(Context ctx, int state) {
        Intent i = new Intent();
        i.setAction(InCallUIActivity.ACTION_CALL_STATE_CHANGE);
        i.putExtra("state", state);
        ctx.sendBroadcast(i);
    }

    /**
     * 挂断电话
     */
    public static synchronized void endCall(Context ctx) {
        Log.d(TAG, "endCall: " + ctx);
        try {
            boolean result = getITelecomService(ctx).endCall();
            Log.d(TAG, "result: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 接听电话
     */
    public static synchronized void answerCall(Context ctx) {
        try {
            getITelecomService(ctx).acceptRingingCall(ctx.getPackageName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 接听电话
     */
    public static synchronized boolean isRinging(Context ctx) {
        try {
            return getITelecomService(ctx).isRinging(ctx.getPackageName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }


    @SuppressLint("PrivateApi")
    public static ITelephony getITelephony(Context context) throws Exception {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);

        final Method getITelephony = telephonyManager.getClass().getDeclaredMethod("getITelephony", (Class[]) null);
        getITelephony.setAccessible(true);
        return (ITelephony) getITelephony.invoke(telephonyManager, (Object[]) null);
    }


    @SuppressLint("PrivateApi")
    public static ITelecomService getITelecomService(Context context) throws Exception {
        TelecomManager telecomManager = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            telecomManager = (TelecomManager) context.getSystemService(Service.TELECOM_SERVICE);
        }

        final Method getITelephony = telecomManager.getClass().getDeclaredMethod("getTelecomService", (Class[]) null);
        getITelephony.setAccessible(true);
        return (ITelecomService) getITelephony.invoke(telecomManager, (Object[]) null);
    }


    public static void openSpeaker(Context mContext) {
        try {
            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            final boolean speakerphoneOn = audioManager.isSpeakerphoneOn();
            Log.d(TAG, "openSpeaker: " + speakerphoneOn);
            if (!speakerphoneOn) {
                audioManager.setMode(AudioManager.MODE_IN_CALL);
                audioManager.setSpeakerphoneOn(true);
                // 设置扬声器音量到最大或一个合适的值
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), 0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 进入SCO模式
     */
    public static void openBluetoothScoMode(Context context) {
        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        mAudioManager.startBluetoothSco();
        mAudioManager.setBluetoothScoOn(true);
        mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);

    }

    /**
     * 关闭SCO
     */
    public static void closeBluetoothScoMode(Context context) {
        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (mAudioManager.isBluetoothScoOn()) {
            mAudioManager.setBluetoothScoOn(false);
            mAudioManager.stopBluetoothSco();
            mAudioManager.setMode(AudioManager.MODE_IN_CALL);
        }

    }


    @SuppressLint("MissingPermission")
    public static void updateCallLog(Context context) {

        Cursor cursor = context.getContentResolver().query(
                CallLog.Calls.CONTENT_URI, new String[]{CallLog.Calls.NUMBER, CallLog.Calls.DATE},
                " type=? and new=?",
                new String[]{CallLog.Calls.MISSED_TYPE + "", "1"}, "date desc");
        try {
            if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
                final String number = cursor.getString(cursor.getColumnIndex(CallLog.Calls.NUMBER));
                long date = cursor.getLong(cursor.getColumnIndex(CallLog.Calls.DATE));
                ContentValues values = new ContentValues(1);
                values.put(CallLog.Calls.TYPE, "5");
                final int update = context.getContentResolver().update(CallLog.Calls.CONTENT_URI
                        , values
                        , "date =? AND number=?"
                        , new String[]{String.valueOf(date), number});

                Log.d(TAG, "updateCallLog: " + update);
            }
        } finally {
            if (cursor != null) cursor.close();
        }

    }

    //关闭扬声器
    public static void closeSpeaker(Context mContext) {
        Log.d(TAG, "closeSpeaker: ");
        try {
            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setMode(AudioManager.MODE_NORMAL);
            if (audioManager.isSpeakerphoneOn()) {
                audioManager.setSpeakerphoneOn(false);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据电话号码查询联系人名称
     *
     * @param context  上下文对象
     * @param phoneNum 电话号码
     * @return
     */
    public static String getContactNameFromPhoneBook(Context context, String phoneNum) {
        Log.d(TAG, "getContactNameFromPhoneBook phoneNum:" + phoneNum);
        if (TextUtils.isEmpty(phoneNum)) {
            return "";
        }
        String number = phoneNum.replace(" ", "").replace("(", "").replace(")", "").replace("-", "");
        Log.d(TAG, "getContactNameFromPhoneBook number:" + number);
        String contactName = "";
        ContentResolver cr = context.getContentResolver();
        Cursor cursor = null;
        try {
            Uri lookupUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                    Uri.encode(number));
            cursor = cr.query(lookupUri, null, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return contactName;
    }


    private static String getAbleSDPath() {
        String path = Environment.getExternalStorageDirectory()
                .getAbsolutePath();
        long size = getAvailableSize(path);
        if (size < 1024 * 1024 * 10) {
            String exPath = getExternalSDCardDirectory();
            if (!exPath.equals(path)) {
                long availableSize = getAvailableSize(exPath);
                if (availableSize < 1024 * 1024 * 10) {
                    return path;
                } else {
                    return exPath;
                }
            }
        }
        return path;
    }

    // 获取当前路径，可用空间
    private static long getAvailableSize(String path) {
        try {
            File base = new File(path);
            StatFs stat = new StatFs(base.getPath());
            long nAvailableCount = stat.getBlockSize()
                    * ((long) stat.getAvailableBlocks());
            return nAvailableCount;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    private static String getExternalSDCardDirectory() {
        File innerDir = Environment.getExternalStorageDirectory();
        File rootDir = innerDir.getParentFile();
        File firstExtSdCard = innerDir;
        File[] files = rootDir.listFiles();
        for (File file : files) {
            if (file.compareTo(innerDir) != 0) {
                firstExtSdCard = file;
                break;
            }
        }
        return firstExtSdCard.getAbsolutePath();
    }


    public static String getImageUri(String phoneNumber) {
        return Utils.getAbleSDPath() + "/doki/imagecahe/" + phoneNumber;
    }

    /**
     * 是否正在普通通话中
     */
    public static boolean isPhoneIdle(Context context) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            return !isInCall(context);
        }
        boolean isIdle = false;
        try {
            //反射获得系统服务的getService方法对象
            Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
            //执行这个方法得到一个IBinder对象
            IBinder binder = (IBinder) method.invoke(null, new Object[]{"phone"});
            //转换为具体的服务类(ITelephony)接口对象
            ITelephony iTelephony = ITelephony.Stub.asInterface(binder);
            if (iTelephony != null) {
                isIdle = iTelephony.isIdle(context.getPackageName());
            }
        } catch (Exception e) {
        }
        return isIdle;
    }

    @SuppressLint("MissingPermission")
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean isInCall(Context context) {
        TelecomManager tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);

        return tm.isInCall();
    }

    public static boolean isHeadsetPluggedIn(Context context) {
        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        return audioManager.isWiredHeadsetOn() || audioManager.isBluetoothA2dpOn();
    }

    public static void setMicrophoneMute(Context mContext, boolean isMicrophoneMute) {
        try {
            AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
            audioManager.setMicrophoneMute(isMicrophoneMute);
            final boolean speakerphoneOn = audioManager.isSpeakerphoneOn();
            Log.d(TAG, "setMicrophoneMute: " + isMicrophoneMute);
            if (!speakerphoneOn) {
                audioManager.setSpeakerphoneOn(true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static int getRawContactId(Context context, String phone) {
        int rawContactId = -1;
        String[] projection = new String[]{ContactsContract.RawContacts._ID};
        String selection = ContactsContract.RawContacts.CONTACT_ID + "=?";
        String[] selectionArgs = new String[]{String.valueOf(getContactId(context,phone))};
        Cursor cursor = context.getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI, projection, selection, selectionArgs, null);
        try {
            if(cursor != null && cursor.moveToFirst()){
                rawContactId = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.RawContacts._ID));
                Logger.e(TAG, " Raw Contact Id: " + rawContactId);
            }

        }catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return rawContactId;
    }

    public static int getContactId(Context context, String phone) {
        int contactId = -1;

        Uri uriNumber2Contacts = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, phone);
        // 查询Uri，返回数据集
        Cursor cursor = context.getContentResolver().query(uriNumber2Contacts, null, null, null, null);
        try {
            if (cursor != null && cursor.moveToNext()) {
                contactId = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.PhoneLookup._ID));
                Logger.e(TAG, "contactId=" + contactId);
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return contactId;
    }


    public static void saveLog(String content) {
        if (!BuildConfig.DEBUG) {
            return;
        }
        final String message = DateUtils.formatDateTime(System.currentTimeMillis()) + " " + content;
        AsyncTask.execute(() -> {

            //创建一个带缓冲区的输出流
            String state = Environment.getExternalStorageState();
            if (state.equals(Environment.MEDIA_MOUNTED)) {
                String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
                String logPath = sdPath + "/Call/log/";
                File file = new File(logPath);
                FileOutputStream fos = null;
                OutputStreamWriter writer = null;
                try {
                    if (!file.exists()) {
                        file.mkdirs();
                    }
                    File logFile = new File(file, "call_log.txt");
                    fos = new FileOutputStream(logFile, true);
                    writer = new OutputStreamWriter(fos, "utf-8");
                    writer.write(message);
                    writer.write("\n");

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (writer != null) {
                            writer.close();
                        }

                        if (fos != null) {
                            fos.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }
}
